package com.yao.myioc.utils;

import com.yao.myioc.utils.support.PrimitiveClassSupport;
import com.yao.myioc.utils.support.impl.IntClassSupport;

import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;

/**
 * 反射工具类
 *
 * @author yao
 */
public class ReflectUtils {

    private static List<PrimitiveClassSupport> classSupports = new ArrayList<>();

    static {
        classSupports.add(new IntClassSupport());
        // todo 添加其他类型
    }

    /**
     * 使用构造器创建bean的实例
     *
     * @param clazz
     * @param args
     * @return
     */
    public static Object createObject(Class<?> clazz, Object... args) {
        try {
            Constructor<?> constructor = clazz.getConstructor();
            // 默认调用无参构造进行对象的创建
            return constructor.newInstance(args);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    public static void setProperty(Object beanInstance, String name, Object valueToUse) {
        try {
            Class<?> clazz = beanInstance.getClass();
            Field field = clazz.getDeclaredField(name);
            Class<?> type = field.getType();
            field.setAccessible(true);
            // 判断是否是基本数据类型
            if (type.isPrimitive()) {
                // 判断是那种基本数据类型
                setPrimitiveClass(field, beanInstance, valueToUse, type);
            } else {
                field.set(beanInstance, valueToUse);
            }

        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    private static void setPrimitiveClass(Field field, Object beanInstance, Object valueToUse, Class<?> type) {
        for (PrimitiveClassSupport pcs : classSupports) {
            if (pcs.isSupport(type)) {
                try {
                    pcs.setProperty(field,beanInstance,valueToUse);
                    return;
                } catch (IllegalAccessException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    public static Class<?> getTypeByFieldName(String beanClassName, String name) {
        try {
            Class<?> clazz = Class.forName(beanClassName);
            Field field = clazz.getDeclaredField(name);
            return field.getType();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    public static void invokeMethod(Object beanInstance, String initMethod) {
        try {
            Class<?> clazz = beanInstance.getClass();
            Method method = clazz.getDeclaredMethod(initMethod);
            // 设置允许访问私有方法和变量，此处也称之为暴力破解
            method.setAccessible(true);
            method.invoke(beanInstance);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

}
